package rpg.engine.client;

import java.util.Collections;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicBoolean;

import rpg.client.Instruction;
import rpg.client.model.GameObject;
import rpg.client.model.Position;
import rpg.engine.model.GameEffect;
import rpg.engine.model.When;
import rpg.util.Objects;
import rpg.util.Strings;

public class GameObjectInfo {
	public enum ObjectType {
		STATIONARY {
			public Instruction toInstruction(String playerID, GameObjectInfo goi)  {
				return Instruction.useObject(playerID, goi.getId(), goi.getName());
			}
			
		}, 
		MOVER {
			public Instruction toInstruction(String playerID, GameObjectInfo goi)  {
				return Instruction.mover(playerID, goi.getId(), goi.getName());
			}
		};
		
		public abstract Instruction toInstruction(String playerID, GameObjectInfo goi);
	}

	public static final List<GameObjectInfo> EMPTY_LIST = Collections.emptyList();

	public static class Builder {
		public Builder()  {
			super();
		}
		
		private List<GameEffect> effects = new Vector<GameEffect>();
		public Builder effect(GameEffect e)  {
			effects.add(e);
			return this;
		}
		
		private boolean active = true;
		public Builder active(boolean b)  {
			active = b;
			return this;
		}

		private String id = "";
		public Builder id(String s) {
			id = Strings.trim(s);
			return this;
		}

		private String name = "";
		public Builder name(String s) {
			name = Strings.trim(s);
			return this;
		}

		private Position position = Position.VOID;
		public Builder position(Position p) {
			position = p;
			return this;
		}
		
		private ObjectType type = ObjectType.STATIONARY;
		public Builder type(ObjectType t)  {
			type = t;
			return this;
		}

		private boolean wearable = false;
		public Builder wearable(boolean b)  {
			wearable = b;
			return this;
		}

		private List<When> whens = new Vector<When>();
		public Builder when(When when) {
			whens.add(when);
			return this;
		}
		
		public GameObjectInfo build()  {
			return new GameObjectInfo(this);
		}
	}

	private final String id;
	public String getId()  {
		return id;
	}

	private final String name;
	public String getName()  {
		return name;
	}
	
	private Position position;
	public Position getPosition()  {
		return position;
	}
	
	private final ObjectType type;
	private final AtomicBoolean active;
	private final List<GameEffect> effects;
	private final List<When> whens;
	public List<When> getWhens()  {
		return whens;
	}
	
	private GameObjectInfo(Builder b)  {
		super();
		id = Strings.requireNonEmpty(b.id, "GameObjectInfo.id");
		name = Strings.requireNonEmpty(b.name, "GameObjectInfo.name");
		position = Objects.requireNonNull(b.position, "GameObjectInfo.position");
		type = Objects.requireNonNull(b.type, "GameObjectInfo.type");
		active = new AtomicBoolean(b.active);
		effects = Collections.unmodifiableList(b.effects);
		wearable = b.wearable;
		whens = Collections.unmodifiableList(b.whens);
	}
	
	public boolean isActive() {
		return active.get();
	}
	
	public void setActive(final boolean b) {
		active.set(b);
	}

	public GameObject toGameObject() {
		return new GameObject(this);
	}

	public List<GameEffect> getEffects() {
		return effects;
	}

	public Instruction toInstruction(String playerID) {
		return type.toInstruction(playerID, this);
	}

	private final boolean wearable;
	public boolean isWearable() {
		return wearable;
	}
}
